﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.Extras.iWare.Wms.Util.LowCode.Front.Model;
using Furion.FriendlyException;
using iWare.Wms.Core;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace iWare.Wms.Application
{
    /// <summary>
    /// 仓库字典值服务
    /// </summary>
    [Route("api/WareDictData")]
    [ApiDescriptionSettings("仓库基础数据", Name = "DictData", Order = 200)]

    public class WareDictDataService : IDynamicApiController, ITransient
    {
        private readonly IRepository<WareDicType> _wareDicTypeRep; //仓库字典类型仓储
        private readonly IRepository<WareDictData, MasterDbContextLocator> _wareDictDataRep; //仓库字典值仓储

        #region 默认
        /// <summary>
        /// 默认
        /// </summary>
        /// <param name="wareDicTypeRep"></param>
        /// <param name="wareDictDataRep"></param>
        public WareDictDataService(
            IRepository<WareDicType> wareDicTypeRep,
            IRepository<WareDictData, MasterDbContextLocator> wareDictDataRep
        )
        {
            _wareDicTypeRep = wareDicTypeRep;
            _wareDictDataRep = wareDictDataRep;
        }
        #endregion

        /// <summary>
        /// 分页查询仓库字典值
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("page")]
        public async Task<PageResult<WareDictDataOutput>> Page([FromQuery] WareDictDataSearch input)
        {
            bool supperAdmin = CurrentUserInfo.IsSuperAdmin;
            var code = !string.IsNullOrEmpty(input.Code?.Trim());
            var value = !string.IsNullOrEmpty(input.Value?.Trim());

            return await _wareDictDataRep.DetachedEntities
                .Where(u => u.TypeId == input.TypeId)
                .Where(u => (u.Status != CommonStatus.DELETED && !supperAdmin) || (u.Status <= CommonStatus.DELETED && supperAdmin))
                .Where((code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")),
                 (value, u => EF.Functions.Like(u.Value, $"%{input.Value.Trim()}%")))
                .OrderBy(u => u.Sort)
                .ProjectToType<WareDictDataOutput>()
                .ToADPagedListAsync(input.PageNo, input.PageSize);
        }

        /// <summary>
        /// 获取某个字典类型下字典值列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("list")]
        public async Task<List<WareDictData>> GetWareDictDataList([FromQuery] QueryWareDictDataListInput input)
        {
            return await _wareDictDataRep.DetachedEntities.Where(u => u.TypeId == input.TypeId)
                .Where(u => u.Status != CommonStatus.DELETED)
                .OrderBy(u => u.Sort)
                .ToListAsync();
        }

        /// <summary>
        /// 获取某个字典类型下字典值列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("listbycode")]
        public async Task<List<Front_Option>> GetWareDictDataListByCode([FromQuery] QueryWareDictDataListByCodeInput input)
        {
            var typeid = await _wareDicTypeRep.Where(x => x.Code == input.Code).Select(x => x.Id).FirstOrDefaultAsync();

            return await _wareDictDataRep.DetachedEntities.Where(u => u.TypeId == typeid)
                .Where(u => u.Status != CommonStatus.DELETED)
                .OrderBy(u => u.Sort)
                .Select(u => new Front_Option() { Label = u.Value, Value = u.Code })
                .ToListAsync();
        }

        /// <summary>
        /// 获取某个字典类型下字典值列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("listbycodelist")]
        public async Task<List<List<Front_Option>>> GetWareDictDataListByCodeList([FromQuery] QueryWareDictDataListByCodeInput input)
        {
            var wareTypeIdList = await _wareDicTypeRep.Where(x => input.CodeList.Contains(x.Code)).Select(x => x.Id).ToListAsync();
            List<List<Front_Option>> ListtemList = new List<List<Front_Option>>();
            foreach (var item in wareTypeIdList)
            {
                var itemList = await _wareDictDataRep.DetachedEntities.Where(u => u.TypeId == item)
                  .Where(u => u.Status != CommonStatus.DELETED)
                  .OrderBy(u => u.Sort)
                  .Select(u => new Front_Option() { Label = u.Value, Value = u.Code })
                  .ToListAsync();
                ListtemList.Add(itemList);
            }
            return ListtemList;
        }

        /// <summary>
        /// 新增仓库字典值表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("add")]
        public async Task Add(AddWareDictDataInput input)
        {
            var isExist = await _wareDictDataRep.AnyAsync(u => (u.Code == input.Code || u.Value == input.Value) && u.TypeId == input.TypeId, false);
            if (isExist) throw Oops.Oh(ErrorCode.D3003);

            var wareDictData = input.Adapt<WareDictData>();
            await _wareDictDataRep.InsertAsync(wareDictData);
        }

        /// <summary>
        /// 删除仓库字典值表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("delete")]
        public async Task Delete(DeleteWareDictDataInput input)
        {
            var wareDictData = await _wareDictDataRep.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (wareDictData == null) throw Oops.Oh(ErrorCode.D3004);
            if (wareDictData.Status == CommonStatus.DELETED)
            {
                await wareDictData.DeleteAsync();
            }
            else
            {
                wareDictData.Status = CommonStatus.DELETED;
                wareDictData.IsDeleted = true;
            }
        }

        /// <summary>
        /// 更新仓库字典值表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("edit")]
        public async Task Update(UpdateWareDictDataInput input)
        {
            var isExist = await _wareDictDataRep.AnyAsync(u => u.Id == input.Id, false);
            if (!isExist) throw Oops.Oh(ErrorCode.D3004);

            // 排除自己并且判断与其他是否相同
            isExist = await _wareDictDataRep.AnyAsync(u => (u.Value == input.Value || u.Code == input.Code) && u.TypeId == input.TypeId && u.Id != input.Id, false);
            if (isExist) throw Oops.Oh(ErrorCode.D3003);

            var wareDictData = input.Adapt<WareDictData>();
            await _wareDictDataRep.UpdateAsync(wareDictData, ignoreNullValues: true);
        }

        /// <summary>
        /// 字典值详情
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("detail")]
        public async Task<WareDictData> GetDictData([FromQuery] QueryWareDictDataInput input)
        {
            return await _wareDictDataRep.FirstOrDefaultAsync(u => u.Id == input.Id, false);
        }

        /// <summary>
        /// 修改字典值状态
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("changeStatus")]
        public async Task ChangeWareDictDataStatus(ChageStateWareDictDataInput input)
        {
            var wareDictData = await _wareDictDataRep.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (wareDictData == null) throw Oops.Oh(ErrorCode.D3003);

            if (!Enum.IsDefined(typeof(CommonStatus), input.Status))
                throw Oops.Oh(ErrorCode.D3005);

            wareDictData.Status = input.Status;
            wareDictData.IsDeleted = false;
        }

        /// <summary>
        /// 根据字典类型Id获取字典值集合
        /// </summary>
        /// <param name="wareDicTypeId"></param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<WareDictData>> GetDictDataListByDictTypeId(long wareDicTypeId)
        {
            return await _wareDictDataRep.DetachedEntities.Where(u => u.WareDictType.Id == wareDicTypeId)
                                                          .Where(u => u.Status == CommonStatus.ENABLE).OrderBy(u => u.Sort)
                                                          .ToListAsync();
        }

        /// <summary>
        /// 删除字典下所有值
        /// </summary>
        /// <param name="wareDicTypeId"></param>
        [NonAction]
        public async Task DeleteByTypeId(long wareDicTypeId)
        {
            var wareDictData = await _wareDictDataRep.Where(u => u.TypeId == wareDicTypeId).ToListAsync();
            await _wareDictDataRep.DeleteAsync(wareDictData);
        }
    }
}
